package hamaster.jpbc.gui;

import static hamaster.jpbc.gui.Messages.getString;
import static hamaster.jpbc.userconfig.ConfigKeys.DEFAULT_ID_FILE;
import static hamaster.jpbc.userconfig.ConfigKeys.LAST_CIPHER_OPEN_FOLDER;
import static hamaster.jpbc.userconfig.ConfigKeys.LAST_PLAIN_SAVE_FOLDER;
import static hamaster.jpbc.util.SwingUtil.setLocationCenter;
import static java.awt.FlowLayout.LEFT;
import static java.awt.FlowLayout.RIGHT;
import static javax.swing.BoxLayout.Y_AXIS;
import static javax.swing.JFileChooser.DIRECTORIES_ONLY;
import static javax.swing.JOptionPane.showMessageDialog;
import hamaster.jpbc.Main;
import hamaster.jpbc.gui.callback.AsynchronousCallback;
import hamaster.jpbc.mgr.AsymmetricDecryptManager;
import hamaster.jpbc.mgr.SymmetricDecryptManager;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.Properties;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.filechooser.FileNameExtensionFilter;

/**
 * 解密操作面板
 * @author <a href="mailto:wangyeee@gmail.com">Wang Ye</a>
 */
public class DecryptPanel extends JPanel implements ActionListener, AsynchronousCallback {
	private static final long serialVersionUID = 1L;

	private Main application;
	private ChooseFilePanel chooseCipherPanel;
	private ChooseFilePanel chooseIDPanel;
	private ChooseFilePanel chooseFolderPanel;
	private JButton decryptButton;
	private JProgressBar progressBar;

	public DecryptPanel(Main application) {
		setLayout(new BoxLayout(this, Y_AXIS));
		this.application = application;
		chooseCipherPanel = new ChooseFilePanel(Messages.getString("DecryptPanel.selectCipher")); //$NON-NLS-1$
		chooseIDPanel = new ChooseFilePanel(Messages.getString("DecryptPanel.selectID")); //$NON-NLS-1$
		chooseFolderPanel = new ChooseFilePanel(Messages.getString("DecryptPanel.selectDest")); //$NON-NLS-1$

		String recentID = Main.getUserConfig().getProperty(DEFAULT_ID_FILE);
		if (recentID != null)
			chooseIDPanel.setCurrentDirectory(new File(recentID));
		String recentCipher = Main.getUserConfig().getProperty(LAST_CIPHER_OPEN_FOLDER);
		if (recentCipher != null)
			chooseCipherPanel.setCurrentDirectory(new File(recentCipher));
		String recentPlain = Main.getUserConfig().getProperty(LAST_PLAIN_SAVE_FOLDER);
		if (recentPlain != null)
			chooseFolderPanel.setCurrentDirectory(new File(recentPlain));

		decryptButton = new JButton(Messages.getString("DecryptPanel.decrypt")); //$NON-NLS-1$
		progressBar = new JProgressBar();
		chooseCipherPanel.setFileFilter(new FileNameExtensionFilter(Messages.getString("DecryptPanel.ibeExtenction"), "ibe"));  //$NON-NLS-1$//$NON-NLS-2$
		chooseIDPanel.setFileFilter(new FileNameExtensionFilter(Messages.getString("DecryptPanel.idExtenction"), "id"));  //$NON-NLS-1$//$NON-NLS-2$
		chooseFolderPanel.setFileSelectionMode(DIRECTORIES_ONLY);
		decryptButton.addActionListener(this);
		progressBar.setValue(0);
		JPanel progressPanel = new JPanel(new FlowLayout(LEFT));
		progressPanel.add(new JLabel(Messages.getString("DecryptPanel.decryptProgress"))); //$NON-NLS-1$
		progressPanel.add(progressBar);
		JPanel buttonPanel = new JPanel(new FlowLayout(RIGHT));
		buttonPanel.add(decryptButton);
		add(chooseCipherPanel);
		add(chooseIDPanel);
		add(chooseFolderPanel);
		add(progressPanel);
		add(buttonPanel);
		setVisible(true);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == this.decryptButton) {
			// 验证密文
			File meta = new File(chooseCipherPanel.getSelectedFilePath());
			if (!meta.exists()) {
				showMessageDialog(application, Messages.getString("DecryptPanel.metaNotExist"), getString("EncryptPanel.error"), JOptionPane.ERROR_MESSAGE); //$NON-NLS-1$ //$NON-NLS-2$
				return;
			}
			if (!meta.canRead()) {
				showMessageDialog(application, Messages.getString("DecryptPanel.cannotReadMeta"), getString("EncryptPanel.error"), JOptionPane.ERROR_MESSAGE); //$NON-NLS-1$ //$NON-NLS-2$
				return;
			}
			// 验证个人参数
			File idFile = new File(chooseIDPanel.getSelectedFilePath());
			if (!idFile.exists()) {
				showMessageDialog(application, Messages.getString("DecryptPanel.IDNotExist"), getString("EncryptPanel.error"), JOptionPane.ERROR_MESSAGE); //$NON-NLS-1$ //$NON-NLS-2$
				return;
			}
			if (!idFile.canRead()) {
				showMessageDialog(application, Messages.getString("DecryptPanel.cannotReadID"), getString("EncryptPanel.error"), JOptionPane.ERROR_MESSAGE); //$NON-NLS-1$ //$NON-NLS-2$
				return;
			}
			// 验证保存路径
			File saveFolder = new File(chooseFolderPanel.getSelectedFilePath());
			if (!saveFolder.exists()) {
				if (!saveFolder.mkdirs()) {
					showMessageDialog(application, Messages.getString("DecryptPanel.cannotSave"), getString("EncryptPanel.error"), JOptionPane.ERROR_MESSAGE); //$NON-NLS-1$ //$NON-NLS-2$
					return;
				}
			}
			if (!saveFolder.isDirectory()) {
				showMessageDialog(application, Messages.getString("DecryptPanel.selectFolder"), getString("EncryptPanel.error"), JOptionPane.ERROR_MESSAGE); //$NON-NLS-1$ //$NON-NLS-2$
				return;
			}
			if (!saveFolder.canWrite()) {
				showMessageDialog(application, Messages.getString("DecryptPanel.cannotWrite"), getString("EncryptPanel.error"), JOptionPane.ERROR_MESSAGE); //$NON-NLS-1$ //$NON-NLS-2$
				return;
			}
			SymmetricDecryptManager decryptManager = new AsymmetricDecryptManager(meta, idFile, saveFolder, this);
			Thread t = new Thread(decryptManager);
			t.start();
			Main.getUserConfig().setProperty(LAST_CIPHER_OPEN_FOLDER, meta.getParent());
			Main.getUserConfig().setProperty(LAST_PLAIN_SAVE_FOLDER, saveFolder.getAbsolutePath());
			Main.getUserConfig().setProperty(DEFAULT_ID_FILE, chooseIDPanel.getSelectedFilePath());
		}
	}

	public void enableVerify(File signed, Properties metadata) {
		JDialog dialog = new JDialog(application);
		dialog.setTitle(Messages.getString("DecryptPanel.2")); //$NON-NLS-1$
		VerifyPanel vp = new VerifyPanel(application);
		vp.enable(signed, metadata);
		dialog.add(vp);
		dialog.setSize(getSize().width, getSize().height * 2);
		dialog.setLocationByPlatform(true);
		setLocationCenter(dialog);
		dialog.setVisible(true);
	}

	@Override
	public void progressUpdated(int progress) {
		if (progress < 0)
			this.progressBar.setValue(0);
		else if (progress <= 100)
			this.progressBar.setValue(progress);
		else
			this.progressBar.setValue(100);
	}

	@Override
	public void message(String content, int type) {
		switch (type) {
		case JOptionPane.ERROR_MESSAGE:
			showMessageDialog(application, content, getString("EncryptPanel.error"), type); //$NON-NLS-1$
			break;
		case JOptionPane.INFORMATION_MESSAGE:
			showMessageDialog(application, content, getString("EncryptPanel.information"), type); //$NON-NLS-1$
			break;
		case JOptionPane.WARNING_MESSAGE:
			showMessageDialog(application, content, getString("EncryptPanel.warning"), type); //$NON-NLS-1$
			break;
		case JOptionPane.QUESTION_MESSAGE:
			showMessageDialog(application, content, getString("EncryptPanel.question"), type); //$NON-NLS-1$
			break;
		case JOptionPane.PLAIN_MESSAGE:
			showMessageDialog(application, content, new String(), type);
			break;
		default:
			if (type == AsynchronousCallback.TITLE_MESSAGE) {
				application.setTitle(content);
			}
		}
	}
}
